package com.bottle.config;

import com.bottle.enity.TokenAuth;
import com.bottle.enity.User;
import com.bottle.enity.UserBridge;
import com.bottle.mode.BridgeInfo;
import com.bottle.mode.UserInfo;
import com.bottle.service.UserService;
import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
public class CacheConfig {

    @Autowired
    private UserService userService;

    @Bean
    public LoadingCache<String, Optional<UserInfo>> getLoadingCache() {
        // 缓存接口这里是LoadingCache，LoadingCache在缓存项不存在时可以自动加载缓存
        LoadingCache<String, Optional<UserInfo>> studentCache
                // CacheBuilder的构造函数是私有的，只能通过其静态方法newBuilder()来获得CacheBuilder的实例
                = CacheBuilder.newBuilder()
                // 设置并发级别为8，并发级别是指可以同时写缓存的线程数
                .concurrencyLevel(8)
                // 设置写缓存后600秒钟过期
                .expireAfterWrite(600, TimeUnit.SECONDS)
                // 设置缓存容器的初始容量为100
                .initialCapacity(1000)
                // 设置缓存最大容量为10000，超过10000之后就会按照LRU最近虽少使用算法来移除缓存项
                .maximumSize(100000)
                // 设置要统计缓存的命中率
                .recordStats()
                // 设置缓存的移除通知
                .removalListener(notification -> {
//                    System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
                })
                // build方法中可以指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
                .build(new CacheLoader<String, Optional<UserInfo>>() {
                    @Override
                    public Optional<UserInfo> load(String code) throws Exception {
                        User user = userService.getUserById(code);
                        UserInfo userInfo = new UserInfo();
                        if(user!=null){
                            userInfo.setUserId(user.getId());
                            List<UserBridge> ubList = userService.getEncryptionIdsByUserId(code);
                            Set<String> ubSet= new HashSet<>();
                            ubList.forEach(x->ubSet.add(x.getEncryptionId()));
                            userInfo.setEncryptionIds(ubSet);
                        }
                        //如果为不空就就返回对象
                        return Optional.of(userInfo);
                    }
                });
        return studentCache;
    }

    @Bean
    public LoadingCache<String, Optional<BridgeInfo>> getBridgeInfoCache() {
        // 缓存接口这里是LoadingCache，LoadingCache在缓存项不存在时可以自动加载缓存
        LoadingCache<String, Optional<BridgeInfo>> cache
                // CacheBuilder的构造函数是私有的，只能通过其静态方法newBuilder()来获得CacheBuilder的实例
                = CacheBuilder.newBuilder()
                // 设置并发级别为8，并发级别是指可以同时写缓存的线程数
                .concurrencyLevel(8)
                // 设置写缓存后600秒钟过期
                .expireAfterWrite(600, TimeUnit.SECONDS)
                // 设置缓存容器的初始容量为100
                .initialCapacity(1000)
                // 设置缓存最大容量为10000，超过10000之后就会按照LRU最近虽少使用算法来移除缓存项
                .maximumSize(100000)
                // 设置要统计缓存的命中率
                .recordStats()
                // 设置缓存的移除通知
                .removalListener(notification -> {
//                    System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
                })
                // build方法中可以指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
                .build(new CacheLoader<String, Optional<BridgeInfo>>() {
                    @Override
                    public Optional<BridgeInfo> load(String code) throws Exception {
                        Set<String> list =userService.getUserIdByEncryptionId(code);
                        BridgeInfo bridgeInfo=new BridgeInfo();
                        if(!list.isEmpty()){
                            bridgeInfo.setUserIds(list);
                        }
                        //如果为不空就就返回对象
                        return Optional.of(bridgeInfo);
                    }
                });
        return cache;
    }

    @Bean
    public LoadingCache<String, Optional<TokenAuth>> getTokenCahche() {
        // 缓存接口这里是LoadingCache，LoadingCache在缓存项不存在时可以自动加载缓存
        LoadingCache<String, Optional<TokenAuth>> cache
                // CacheBuilder的构造函数是私有的，只能通过其静态方法newBuilder()来获得CacheBuilder的实例
                = CacheBuilder.newBuilder()
                // 设置并发级别为8，并发级别是指可以同时写缓存的线程数
                .concurrencyLevel(8)
                // 设置写缓存后600秒钟过期
                .expireAfterWrite(600, TimeUnit.SECONDS)
                // 设置缓存容器的初始容量为100
                .initialCapacity(1000)
                // 设置缓存最大容量为10000，超过10000之后就会按照LRU最近虽少使用算法来移除缓存项
                .maximumSize(100000)
                // 设置要统计缓存的命中率
                .recordStats()
                // 设置缓存的移除通知
                .removalListener(notification -> {
//                    System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
                })
                // build方法中可以指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
                .build(new CacheLoader<String, Optional<TokenAuth>>() {
                    @Override
                    public Optional<TokenAuth> load(String code) throws Exception {

                        //如果为不空就就返回对象
                        return Optional.absent();
                    }
                });
        return cache;
    }

    @Bean
    public ConcurrentHashMap<String,String> getUserIdCache(){
        ConcurrentHashMap<String,String> map =new ConcurrentHashMap<>();
        return map;
    }
}
